package com.kim.logs.context;

import com.alibaba.fastjson.JSONObject;
import com.kim.logs.eneity.MethodLogInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.text.MessageFormat;

/**
 * @Deacription TODO
 * @Author jianhua.hong
 * @Date 2020/4/2 17:40
 **/
@Slf4j
@Aspect
public class RequestLogHandler extends AbstractLogHandler {
    private static final String REQUEST_MESSAGE_FORMAT = "URL=[{0}],method=[{1}],handle class=[{2}],handle method=[{3}],Param=[{4}],Response=[{5}],cost time=[{6}ms-({7})]";
    private static final String REQUEST_MESSAGE_ERROR_FORMAT = "URL=[{0}],method=[{1}],handle class=[{2}],handle method=[{3}],Param=[{4}]";
    private static final String REQUEST_MESSAGE_MULIT_FORMAT = "URL=[{0}],request method=[{1}],handle class=[{2}],handle method=[{3}]";

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && execution(public * *(..) )")
    public void controllerPoincut() {

    }
    @Around("controllerPoincut()")
    public Object doControllerAround(ProceedingJoinPoint point) throws Throwable {
        Long startTime = System.currentTimeMillis();
        super.processRequestTraceId();
        String traceId = RequestLogContext.getTraceId();
        MethodLogInfo methodLogInfo = super.buildMethodInfo(point);
        Object controllerResp = point.proceed();
        Long endTime = System.currentTimeMillis();
        Long cost = endTime - startTime;
        String path = methodLogInfo.getPath();
        String className = methodLogInfo.getClassName();
        String method = methodLogInfo.getMethod();
        String methodName = methodLogInfo.getMethodName();
        if (!methodLogInfo.isMultiFileMark()) {
            String paramsStr = methodLogInfo.getParamsStr();
            String timeFlag = getTimeCostFlag(cost);
            String controllerRespStr = JSONObject.toJSONString(controllerResp);
            Object[] paramsArray = new Object[]{
                    path, method, className, methodName, paramsStr, controllerRespStr, cost, timeFlag
            };
            log.info("[request-log-around-{}]{}", traceId, MessageFormat.format(REQUEST_MESSAGE_FORMAT, paramsArray));
            log.info("[timec-log-{}],class=[{}],method=[{}],cost time=[{}-({})]", traceId, className, methodName, cost, timeFlag);
        } else {
            Object[] paramsArray = new Object[]{
                    path, method, className, methodName
            };
            log.info("[request-log-around-{}]{}", traceId, MessageFormat.format(REQUEST_MESSAGE_MULIT_FORMAT, paramsArray));
        }
        return controllerResp;
    }
    @AfterThrowing(pointcut = "controllerPoincut()", throwing = "e")
    public void handle(JoinPoint point, Exception e) {
        super.processRequestTraceId();
        String traceId = RequestLogContext.getTraceId();
        MethodLogInfo methodLogInfo = super.buildMethodInfo(point);
        String path = methodLogInfo.getPath();
        String className = methodLogInfo.getClassName();
        String method = methodLogInfo.getMethod();
        String methodName = methodLogInfo.getMethodName();
        String paramsStr = methodLogInfo.getParamsStr();
        Object[] paramsArray = new Object[]{
                path, method, className, methodName, paramsStr
        };
        log.info("[request-log-pre-{}]{}", traceId, MessageFormat.format(REQUEST_MESSAGE_ERROR_FORMAT, paramsArray));
        log.info("[request-log-after-{}],handle class=[{}],handle method=[{}]异常", traceId, className, methodName);
    }
}
